import config from '../../focus.config.js';
import http from './http.js';
import queue from './queue.js';
import sign from './sign.js';
import showToast from './showToast.js';
import { showLoading, hideLoading } from './loading.js';
import toJson from '../data/toJson.js';
import toQueryString from '../data/toQueryString.js';
import runtimeType from '../sys/runtimeType.js';

/**
 * request接口请求【异步方法】
 * @description request接口请求，参数详情请查看配置文件focus.config.js
 * @param {Object} parameter 方法参数
 */
function request(parameter) {
	
	// ------------------------------------------------ 参数预处理
    // 获取当前运行环境
    var runType = runtimeType();
    // 获取配置文件request信息
    var config_request = config.request;
	// 合并 配置文件参数、主动传入参数
	var paramLast = Object.assign({}, config_request, parameter);
	// 传递参数：请求方式method 大写
	paramLast["method"] = paramLast["method"].toUpperCase();
	// 成品请求地址 = 请求地址头 + api地址
	if (paramLast["openHttphead"] == true) { paramLast["url"] = http('get') + paramLast["url"]; }
    
	// ------------------------------------------------ 绿色通道判定
	// 是否允许请求通过
	var isCanReq = false;
	// 绿色通道直接请求
	if (paramLast["openGreen"] == true) { isCanReq = true; }
	else {
		// 队列不拥挤也可请求
		isCanReq = queue('add', paramLast["url"]);
		// 如果是拥挤状态，报错提醒
		if (isCanReq != true)
		{
			// 错误信息对象
			var err_back = { code: 400, data: null, msg: '该接口正在请求中，请稍候' };
			// 进行错误提示
			showToast(paramLast, err_back.msg);
            // 配置文件失败方法
            if (config_request && config_request.fail) { config_request.fail(err_back); }
			// 主动参数的失败方法
			if (parameter && parameter.fail) { parameter.fail(err_back); }
		}
	}
	
	// ------------------------------------------------ 请求方法调用
	// 允许状态，才执行
	if (isCanReq == true)
	{
		// 显示"请求中"提示弹框
		showLoading(paramLast);
		
		// ------------------------------------------------ header请求头
		// 要传递请求头 编辑
		var req_header = {};
        // 1. 配置文件header加入到此数据
        if (config_request["header"]) { for (var key in config_request["header"]) { req_header[key] = config_request.header[key]; } }
        // 2. 添加content-type
		if (paramLast["method"] == "POST") {
			if (paramLast["contentType"] == 1) { req_header['Content-Type'] = 'application/json'; }
			else if (paramLast["contentType"] == 2) { req_header['Content-Type'] = 'application/x-www-form-urlencoded'; }
		}
        // 3. 主动传递参数的header覆盖到此数据
        if (paramLast["header"]) { for (var key in paramLast["header"]) { req_header[key] = paramLast.header[key]; } }
		/** 添加token鉴权
		 * 数据示例：{ "Authorization": 'Bearer ' + 'AD7TGQW98WQFW-D273D87-238G' }
		 * */
		
		// ------------------------------------------------ 传输数据签名
		// 调用生成签名方法
		if (paramLast["openSign"] == true) { paramLast["data"] = sign(paramLast["data"]); }
		
		// ------------------------------------------------ 地址栏传输数据
		// 请求地址取出
		var str_url_api = paramLast["url"];
		// 地址栏数据添加
		for (let key in paramLast["urlData"]) { str_url_api += '/' + encodeURIComponent(paramLast.urlData[key]); }
		
		// ------------------------------------------------ 调用接口请求api
        // 如果是“非UNI”环境
        if (runType == 'nonUNI')
        {
            // 创建 XMLHttpRequest 对象
            var xmlhttp = {};
            if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); }
            else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); }
            
            // 超时限制
            var timeout = setTimeout(()=>{
                // 终止请求
            	xmlhttp.abort();
            	// 清除地址缓存
            	queue('del', paramLast["url"]);
                // 组装返回数据
            	var data_back = { code: 408, data: {}, msg: "请求超时" };
                // 取消loading弹框
                hideLoading(paramLast);
                // 显示提示框
                showToast(paramLast, data_back.msg);
                // 配置文件失败方法
                if (config_request && config_request.fail) { config_request.fail(data_back); }
                // 主动参数的失败方法
                if (parameter && parameter.fail) { parameter.fail(data_back); }
            }, paramLast["timeout"]);
            
            // 要发送的数据封装(只有get请求需要处理)
            if (paramLast["method"] == "GET")
            {
                // 将数据转换为名称/值对编码字符串
                var str_query = toQueryString(paramLast["data"]);
                // 如果转换成功
                if (str_query) { str_url_api = str_url_api + '?' + str_query; }
            }
            
            // 请求实例化
            xmlhttp.open(paramLast["method"], str_url_api, true); // 请求方式和地址
            for (var k in req_header) { xmlhttp.setRequestHeader(k, req_header[k]); } // 请求头数据赋值
            // xmlhttp.withCredentials = true; // 携带cookie
            
            // 服务器响应
            xmlhttp.onreadystatechange = () => {
            	// 链接接口成功
            	if (xmlhttp.readyState == 4 && xmlhttp.status == 200)
            	{
                    // 取消超时限制
                    if (timeout) { clearTimeout(timeout); }
                    // 后端返回的原始字符串数据
            		var str_response = "";
            		if (xmlhttp.responseText) { str_response = xmlhttp.responseText; }
            		else if (xmlhttp.responseXML) { str_response = xmlhttp.responseXML; }
                    // 将数据转换为json
                    var obj_response = toJson(str_response);
                    // 清除地址缓存
                    queue('del', paramLast["url"]);
                    // 取消loading弹框
                    hideLoading(paramLast);
                    // 如果数据转换失败了
                    if (!obj_response)
                    {
                        // 错误提示
                        showToast(paramLast, '返回数据格式错误');
                        // 配置文件失败方法
                        if (config_request && config_request.fail) { config_request.fail(obj_response); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(obj_response); }
                    }
                    // 如果成功code码与规定不符
                    else if (obj_response.code != paramLast['successCode'])
                    {
                    	// 错误提示
                    	showToast(paramLast, obj_response.msg);
                        // 配置文件失败方法
                        if (config_request && config_request.fail) { config_request.fail(obj_response); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(obj_response); }
                    }
                    // 成功回调
                    else {
                        // 配置文件成功方法
                        if (config_request && config_request.success) { config_request.success(obj_response.data); }
                        // 主动参数的成功方法
                        if (parameter && parameter.success) { parameter.success(obj_response.data); }
                    }
            	}
            	// 链接接口失败
            	else if (xmlhttp.readyState == 4)
            	{
                    // 取消超时限制
                    if (timeout) { clearTimeout(timeout); }
                    // 组装返回数据
                    var resD = {
                        code: xmlhttp.status ? xmlhttp.status : 400,
                        data: null,
                        msg: xmlhttp.responseText ? xmlhttp.responseText : null,
                    };
            		// 清除地址缓存
            		queue('del', paramLast["url"]);
            		// 取消loading弹框
            		hideLoading(paramLast);
                    // 错误提示
                    showToast(paramLast, '抱歉，数据请求异常 ' + resD.code);
                    // 配置文件失败方法
                    if (config_request && config_request.fail) { config_request.fail(resD); }
                    // 主动参数的失败方法
                    if (parameter && parameter.fail) { parameter.fail(resD); }
            	}
            };
            
            // 发送请求
            if (paramLast["method"] == "GET") { xmlhttp.send(); }
            else {
            	var str_data = paramLast["data"];
            	if (typeof(str_data)=="object") { str_data = JSON.stringify(str_data); }
            	xmlhttp.send(str_data);
            }
        }
        // 如果是UNI环境
        else {
            // 调用请求api
            uni.request({
            	method: paramLast["method"],
            	url: str_url_api,
            	data: paramLast["data"],
            	header: req_header,
            	timeout: paramLast["timeout"],
            	dataType: paramLast["dataType"],
            	fail: (resD) => {
            		// 清除地址缓存
            		queue('del', paramLast["url"]);
            		// 取消loading弹框
            		hideLoading(paramLast);
            		// 显示提示框 此处数据为框架系统返回数据，所以是errMsg
            		showToast(paramLast, resD.errMsg);
                    // 配置文件失败方法
                    if (config_request && config_request.fail) { config_request.fail(resD); }
                    // 主动参数的失败方法
                    if (parameter && parameter.fail) { parameter.fail(resD); }
            	},
            	success: (resD) => {
            		// 清除地址缓存
            		queue('del', paramLast["url"]);
            		// 取消loading弹框
            		hideLoading(paramLast);
            		// 如果是状态码错误
            		if (resD.statusCode != 200)
            		{
            			// 错误提示
            			showToast(paramLast, '抱歉，数据请求异常 ' + resD.statusCode);
                        // 配置文件失败方法
                        if (config_request && config_request.fail) { config_request.fail(resD.data); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(resD.data); }
            		}
            		// 如果成功code码与规定不符
            		else if (resD.data.code != paramLast['successCode'])
            		{
            			// 错误提示
            			showToast(paramLast, resD.data.msg);
                        // 配置文件失败方法
                        if (config_request && config_request.fail) { config_request.fail(resD.data); }
                        // 主动参数的失败方法
                        if (parameter && parameter.fail) { parameter.fail(resD.data); }
            		}
            		// 成功回调
            		else {
                        // 配置文件成功方法
                        if (config_request && config_request.success) { config_request.success(resD.data.data); }
                        // 主动参数的成功方法
                        if (parameter && parameter.success) { parameter.success(resD.data.data); }
                    }
            	}
            });
        }
        
	}
	
}

export default request;